<?php


namespace app\service;


use support\Redis;

/**
 * 令牌桶算法
 * Class RateLimit
 * @package app\service\api
 */
class RateLimit
{
    /**
     * 节流限制返回
     * @param $uid
     * @return string
     */
    public static function minLimit($uid)
    {
        $minNumKey = $uid . '_minNum';
        $dayNumKey = $uid . '_dayNum';
        $resMin    = self::getRedis($minNumKey, config('ratelimit.minNum'), 60);
        $resDay    = self::getRedis($dayNumKey, config('ratelimit.dayNumKey'), 86400);
        if (!$resMin['status'] || !$resDay['status']) {
            return $resMin['msg']. $resDay['msg'];
        }
    }

    /**
     * 缓存写入
     * @param $key
     * @param $initNum
     * @param $expire
     * @return array
     */
    public static function getRedis($key, $initNum, $expire)
    {
        $nowtime  = time();
        $result   = ['status' => true, 'msg' => ''];
        //监视一个或多个key
        Redis::watch($key);
        $limitVal = Redis::get($key);
        if ($limitVal) {
            $limitVal = json_decode($limitVal, true);
            $newNum   = min($initNum, ($limitVal['num'] - 1) + (($initNum / $expire) * ($nowtime - $limitVal['time'])));
            if ($newNum > 0) {
                $redisVal = json_encode(['num' => $newNum, 'time' => time()]);
            } else {
                return ['status' => false, 'msg' => '请稍后再试！'];
            }
        } else {
            $redisVal = json_encode(['num' => $initNum, 'time' => time()]);
        }
        Redis::multi();
        Redis::setEx($key,$expire, $redisVal);
        $rob_result = Redis::exec();
        if (!$rob_result) {
            $result = ['status' => false, 'msg' => '请稍后再试!'];
        }
        return $result;
    }
}
